package oktx.feign.config;

import com.netflix.loadbalancer.IRule;
import oktx.feign.loadbalance.RestTxLoadBalanceRuleWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * Created by huangdachao on 2018/5/30 15:22.
 */
public class RestBeanPostProcessor implements BeanPostProcessor {
    private static final String FEIGN_CLAZZ_NAME = "feign.ReflectiveFeign$FeignInvocationHandler";

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 1. wrap IRule
        if (bean instanceof IRule) {
            return new RestTxLoadBalanceRuleWrapper((IRule) bean);
        }

        // 2. wrap RestTemplateCustomizer
        if (bean instanceof RestTemplateCustomizer) {
            return new RestTemplateCustomizerWrapper((RestTemplateCustomizer) bean);
        }

        // 3. wrap Feign
        if (!Proxy.isProxyClass(bean.getClass())) {
            return bean;
        }

        InvocationHandler handler = Proxy.getInvocationHandler(bean);
        if (handler.getClass().getName().equals(FEIGN_CLAZZ_NAME)) {
            FeignBeanWrapper h = new FeignBeanWrapper(handler);
            Class<?> clazz = bean.getClass();
            return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), h);
        }
        return bean;
    }
}
